var labelType, useGradients, nativeTextSupport, animate;
(function() {
  var ua = navigator.userAgent,
      iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
      typeOfCanvas = typeof HTMLCanvasElement,
      nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
      textSupport = nativeCanvasSupport 
        && (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
  //I'm setting this based on the fact that ExCanvas provides text support for IE
  //and that as of today iPhone/iPad current text support is lame
  labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
  nativeTextSupport = labelType == 'Native';
  useGradients = nativeCanvasSupport;
  animate = !(iStuff || !nativeCanvasSupport);
})();

var Log = {
  elem: false,
  write: function(text){
    if (!this.elem) 
      this.elem = document.getElementById('log');
    this.elem.innerHTML = text;
  }
};
function make_msc_table(vis, getJSON) {
	function make_table(data) {
		$('#msc_table tbody').html("");
		if (data && (data.length > 0)) {
			data.sort(function(a, b) {
				var result = (a.count < b.count)? -1: (a.count > b.count)? 1: 0;
				result = -result;
				if (result == 0) {
					result = (a.tag < b.tag)? -1: (a.tag > b.tag)? 1: 0;
				}
				return result;
			});
			for (var i in data) {
				var cls = (i % 2 == 0)? "even": "odd";
				$('#msc_table tbody').append('<tr class="' + cls + '"><td><a href="/msc/' + data[i].tag + '">' + data[i].tag + '</a></td><td>'+ data[i].tagText + '</td><td>' + data[i].count + '</td></tr>');
			}
		}
		else {
			$('#msc_table tbody').append('<tr><td></td><td>No results.</td><td></td></tr>');
		}

	};
	Log.write('Loading MSC table');
	var root_id = vis.root;
	if (getJSON == true) {
		$.getJSON('/author-network/graph/?exclude_coauthors=true&include_msc=true&key=' + root_id, function(data) {
			vis.graph.nodes[root_id].data.msc = data[0].data.msc;
			make_table(vis.graph.nodes[root_id].data.msc);
			Log.write('Done');
		})
	}
	else {
		make_table(vis.graph.nodes[root_id].data.msc);
		Log.write('Done');
	}

};

function make_coauthor_table(vis) {
	$('#coauthor_table tbody').html("");
	var root_id = vis.root;
	var data = [];
	var coauthors = vis.graph.nodes[root_id].adjacencies;
	for (var key in coauthors) {
		if (key == root_id) { continue; }
		data.push({'name': key, 'count': coauthors[key].data.count});
	}
	if (data && (data.length > 0)) {
		data.sort(function(a,b) {
			var result = (a.count < b.count)? -1: (a.count > b.count)? 1: 0;
			result = -result;
			if (result == 0) {
				result = (a.name < b.name)? -1: (a.name > b.name)? 1: 0;
			}
			return result;
		}); // sort by weight
		for (var i in data) {
			var cls = (i % 2 == 0)? "even": "odd";
			var row = $('<tr class="' + cls + '"><td class="name">' + data[i].name + '</td><td class="count">' + data[i].count + '</td></tr>');
			row.click(function(eventObj) {
				var node_id = $('td.name', eventObj.currentTarget).first().text();
				$(document.getElementById(node_id)).click();
				// vis.onClick(node_id, {hideLabels:false});
			});
			$('#coauthor_table tbody').append(row);
		}
	}
	else {
		$('#coauthor_table tbody').append('<tr><td>No results.</td><td></td></tr>');
	}

};

function make_selection_list(vis) {
	var root_id = vis.root;
	// focus selections
	$('#focusSelect').html("");
	$('#focusSelect').append('<OPTION value="">' + root_id+ '</OPTION>');
	var nodes = [];
	for (var key in vis.graph.nodes){
		if (key == root_id) { continue; }
		nodes.push(vis.graph.nodes[key]);
	}
	nodes.sort(function(a,b) {return (a.id < b.id)? -1: (a.id > b.id)? 1: 0;});	// sort by id
	for (var i in nodes) {
		$('#focusSelect').append('<OPTION value="">' + nodes[i].id + '</OPTION>');
	}
}
function toJSON(vis) {
	var root_index = 0;
	var count = 0;
	var json = [];
	for (var key in vis.graph.nodes) {
		if (key == vis.root) {
			root_index = count;
		}
		var node = vis.graph.nodes[key];
		var adj = [];
		for (var adj_key in node['adjacencies']) {
			adj.push({
				nodeTo: adj_key,
				data: node['adjacencies'][adj_key]['data'],
			});
		}
		json.push({
			id: node['id'],
			name: node['name'],
			data: node['data'],
			adjacencies: adj,
		});
		count++;
	}
	return {'json': json, 'root_index': root_index};
};



function init_vis(vis, root_id) {
	var url = '/author-network/graph/';
	if (root_id != null) {
		url += '?key=' + root_id;
	}
	//init data
    //If a node in this JSON structure
    //has the "$type" or "$dim" parameters
    //defined it will override the "type" and
    //"dim" parameters globally defined in the
    //RGraph constructor.
	Log.write('Loading graph...');
	$.getJSON(url, function(data) {
		if (root_id != null) {
			var new_data = [];
	 		new_data.push({});
			for (var i in data) {
				if (data[i].id == root_id) {
					new_data[0] = data[i];
				}
				else {
					new_data.push(data[i]);
				}
			}
			data = new_data;
		}
		//load graph.
	    vis.loadJSON(data);
	    //compute positions and plot
	    vis.refresh();
	    //end
	    vis.controller.onBeforeCompute(vis.graph.getNode(vis.root));
	    vis.controller.onAfterCompute();
		Log.write('Done');
	});
	//end data
};

$(function () {
    //init RGraph
	var rgraph_options = {
      'injectInto': 'infovis',
      // //Optional: Add a background canvas
      // //that draws some concentric circles.
      // 'background': {
      //   'CanvasStyles': {
      //     'strokeStyle': '#555',
      //     'shadowBlur': 50,
      //     'shadowColor': '#ccc'
      //   }
      // },
        //Nodes and Edges parameters
        //can be overridden if defined in 
        //the JSON input data.
        //This way we can define different node
        //types individually.
        Node: {
            'overridable': false,
			'transform': true,
             'color': '#cc0000'
        },
        Edge: {
            'overridable': true,
            'color': '#064D6D',
			'lineWidth': 1
        },
		Navigation: {  
		      enable: true,  
		      panning: true,  
		      zooming: 10  
		    },
        //Set polar interpolation.
        //Default's linear.
        interpolation: 'polar',
        //Change the transition effect from linear
        //to elastic.
        // transition: $jit.Trans.linear,
        //Change other animation parameters.
        duration:2000,
        fps: 25,
		withLabels: true,
		clearCanvas: true,
        //Change father-child distance.
        levelDistance: 200,
        //This method is called right before plotting
        //an edge. This method is useful to change edge styles
        //individually.
        onBeforePlotLine: function(adj){
            //Add some random lineWidth to each edge.
            // if (!adj.data.$lineWidth) 
            //     adj.data.$lineWidth = Math.random() * 5 + 1;
			var weight = adj.data.$lineWidth;
			adj.data.$lineWidth = 1;
			if (((adj.nodeFrom._depth == 0) && (adj.nodeTo._depth == 1)) || ((adj.nodeFrom._depth == 1) && (adj.nodeTo._depth == 0))){
				adj.data.$lineWidth = 3;
			}
			// var minDepth = adj.nodeFrom._depth;
			// if (minDepth > adj.nodeTo._depth) minDepth = adj.nodeTo._depth;
			// var weight = 6 - 3*minDepth;
			// if (weight < 1) weight=1;
			//             adj.data.$lineWidth = weight;
        },
        
        onBeforeCompute: function(node){
            Log.write("Centering " + node.name + "...");
            
            // //Make right column relations list.
            // var html = "<h4>" + node.name + "</h4><b>Connections:</b>";
            // html += "<ul>";
            // node.eachAdjacency(function(adj){
            //     var child = adj.nodeTo;
            //     html += "<li>" + child.name + "</li>";
            // });
            // html += "</ul>";
            // $jit.id('inner-details').innerHTML = html;
        },
        //Add node click handler and some styles.
        //This method is called only once for each node/label crated.
        onCreateLabel: function(domElement, node){
			$(domElement).html(node.name);
			domElement.style.cursor = 'pointer';
            domElement.onclick = function () {
				if (node.id != rgraph.root) {
					Log.write("Loading data...");
					// make ajax call to get new tree, sum up the old tree and the new tree, then animate clicking on the element
					$.getJSON('/author-network/graph/?key=' + node.id, function(data) {
						Log.write("Centering " + node.name + "...");
						rgraph.op.sum(data, {'id': node.id,
												'duration': 2000,
												'type': 'fade:con',
												hideLabels: false,
												onComplete: function() {
													// rgraph.onClick(node.id);
													Log.write('Done');
												}
										});
					});
				}
			};

        },
        //This method is called when rendering/moving a label.
        //This is method is useful to make some last minute changes
        //to node labels like adding some position offset.
        onPlaceLabel: function(domElement, node){
			// resize labels
			if (node._depth <= 1){
				$(domElement).removeAttr("class").addClass("nodeLabel nodeLabel" + node._depth);
			}
			else {
				$(domElement).removeAttr("class").addClass("nodeLabel");
			}
            var style = domElement.style;
            var left = parseInt(style.left);
            var w = domElement.offsetWidth;
            style.left = (left - w / 2) + 'px';
        },
        
        onAfterCompute: function(){
			make_selection_list(rgraph);
			make_coauthor_table(rgraph);
			var getJSON = $('#msc_table_container').hasClass('toggled')? true: false;
			Log.write("Loading MSC table");
			make_msc_table(rgraph, getJSON);
			Log.write("Done");            
        }
     };

    var rgraph = new $jit.RGraph(rgraph_options);
	init_vis(rgraph);

	
	// button handlers
	$('.button').button();
	$('#focusButton').click(function() {
		var selected = $('#focusSelect :selected').text();
		var nodesJSON = toJSON(rgraph);
		var json = nodesJSON['json'];
		var root_index = nodesJSON['root_index'];
		$('#infovis').html("");
	    rgraph = new $jit.RGraph(rgraph_options);
		rgraph.loadJSON(json, root_index);
		rgraph.refresh();
		rgraph.controller.onBeforeCompute(rgraph.graph.getNode(rgraph.root));
		rgraph.controller.onAfterCompute();
		$(document.getElementById(selected)).click();
		// rgraph.onClick(selected, {hideLabels:false});
		return false;
	});
	$('#removeBranchesButton').click(function() {
		var root_node = rgraph.graph.getNode(rgraph.root)
		var data = [];
		data.push(root_node)
		for (var key in root_node['adjacencies']) {
			if (key != root_node['id'])	{
				data.push({
					id: key,
					name: key,
					adjacencies: [{
						nodeTo: root_node['id'],
						data: root_node['adjacencies'][key]['data'],
					}],
				})
			}	
		}
		rgraph.loadJSON(data);
		rgraph.refresh();
	    rgraph.controller.onBeforeCompute(rgraph.graph.getNode(rgraph.root));
	    rgraph.controller.onAfterCompute();
		return false;
	});
	$('#msc_table_container').hide();
	$('#msc_toggleButton').click(function() {
		$('#msc_table_container').slideToggle('slow', function(){
			if ($('#msc_table_container').hasClass('toggled')) {
				$('#msc_table_container').removeClass('toggled');
				$('#msc_toggleButton').html('[+]');
			}
			else {
				$('#msc_table_container').addClass('toggled');
				$('#msc_toggleButton').html('[-]');
				make_msc_table(rgraph, true);
			}
		});
		return false;
	});
	$('#coauthor_toggleButton').click(function() {
		$('#coauthor_table_container').slideToggle('slow', function(){
			if ($('#coauthor_table_container').hasClass('toggled')) {
				$('#coauthor_table_container').removeClass('toggled');
				$('#coauthor_toggleButton').html('[+]');
				return false;
			}
			$('#coauthor_table_container').addClass('toggled');
			$('#coauthor_toggleButton').html('[-]');
		});
		return false;
	});
	
	$('#search_results_toogleButton').click(function() {
		$('#search_results_container').slideToggle('slow', function(){
			if ($('#search_results_container').hasClass('toggled')) {
				$('#search_results_container').removeClass('toggled');
				$('#search_results_toogleButton').html('[+]');
				return false;
			}
			$('#search_results_container').addClass('toggled');
			$('#search_results_toogleButton').html('[-]');
		});
		return false;
	});
	
	// custom search
	$('#search_results_container').hide();
	var items_per_page = 10;
	var max_rows = 100;
	var paginationOptions = {
		items_per_page : items_per_page,
		callback: function(new_page_index, pagination_container) {
			$('#search_results_table').html("");
			var search_results = $('#pagination_data_holder').data('search_results');
			for (var i=new_page_index*items_per_page; i < Math.min((new_page_index + 1)*items_per_page, max_rows); i++) {
				if (search_results[i]) {
					var author = search_results[i]['author'];
					var cls = (i % 2 == 0) ? "even": "odd";
					var row = $('<tr class="' + cls + '"><td class="name">' + author + '</td></tr>');
					row.click(function(eventObj) {
						var node_id = $('td.name', eventObj.currentTarget).first().text();
						init_vis(rgraph, node_id);
					});
					$('#search_results_table').append(row);
				}
			}
			},
		};
	$('#searchButton').click(function() {
		var term = $('#searchAuthor').val();
		if (term) {
			Log.write('Loading search results...');
			var url = '/author-network/graph/?is_lucene=true&search=' + term + '&max_rows=' + max_rows;
			$.getJSON(url, function (data) {
				$('#pagination_data_holder').data('search_results', data);
				if (data) {
					$('#paging_container').pagination(data.length, paginationOptions);
					$('#search_results_container').show();
					$('#search_results_container').addClass('toggled');
					$('#search_results_toogleButton').html('[-]');
				}
				Log.write('Done');
			});
		}
	});
	
	
	// search bar
	$("#searchAuthor").autocomplete({
				source: function(request, response) {
						$.ajax({
							url: "/author-network/graph/",
							dataType: "json",
							type: "GET",
							data: {
								maxRows: 12,
								search: request.term
							},
							success: function(data) {
								response($.map(data, function(item) {
											return {
												label: item.author,
												value: item.author
											}
										}));
									},
							});
						},
				minLength: 1,
				select: function(event, ui) {
					init_vis(rgraph, ui.item.value);
				},
				open: function() {
					$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
				},
				close: function() {
					$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
				}
	});
	
});
